package com.zhoug.common.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

import com.zhoug.common.R;
import com.zhoug.common.utils.ResourceUtils;

import androidx.annotation.Nullable;

/**
 * 拍照四周遮罩中间框选取图像
 * 可以移动,缩放
 * @Author HK-LJJ
 * @Date 2020/3/25
 * @Description
 */
public class OverlayView extends View {
    private static final String TAG = "OverlayView";
    //橡皮擦,擦掉矩形中间的内容
    private Paint eraser = new Paint(Paint.ANTI_ALIAS_FLAG);
    //中间矩形的画笔
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    //中间抓取图像的矩形
    protected RectF frameRect = new RectF();
    //中间矩形距离四周的边距
    private int border = 20;
    public static final int SURE_WIDTH = 1;//宽度确定
    public static final int SURE_HEIGHT = 2;//高度确定
    //中间宽高中确定的那一边
    private int sure = SURE_WIDTH;
    private float sureWeight = 0.7f;//确定的那边的权重:0-1
    //中间的宽高比:w/h
    private float ratio = 4 / 3f;
    //四周角的长度
    int cornerLength = 50;
    //四周角宽度
    int cornerLineWidth = 6;
    //遮罩颜色
    private int maskColor = Color.argb(150, 0, 0, 0);
    private int rectColor = Color.WHITE;
    //是否可以缩放
    private boolean scaleEnabled = false;
    //是否可以移动
    private boolean translateEnabled = false;
    /**
     * 触摸点所处的位置
     */
    private static final int CORNER_LEFT_TOP = 1;//左上角
    private static final int CORNER_RIGHT_TOP = 2;
    private static final int CORNER_RIGHT_BOTTOM = 3;
    private static final int CORNER_LEFT_BOTTOM = 4;
    //触摸点在哪个角落
    private int touchCorner = -1;
    //触摸点的矩形的边长偏移量
    private static final int TOUCH_RECT_SIZE = 50;
    //触摸点的矩形:以触摸点为中心,TOUCH_RECT_SIZE为边长的正方形
    private RectF touchRect = new RectF();
    protected boolean drawFrameRect=true;
    protected boolean drawCornerLine=true;

    //手势事件
    private GestureDetector gestureDetector;
    private GestureDetector.SimpleOnGestureListener onGestureListener = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            super.onScroll(e1, e2, distanceX, distanceY);
            translate(distanceX, distanceY);
            return true;
        }
    };

    public OverlayView(Context context) {
        this(context, null);
    }

    public OverlayView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);

    }

    public OverlayView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        parseAttribute(context, attrs, defStyleAttr);
        init(context);
    }

    /**
     * 解析属性
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    protected void parseAttribute(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.OverlayView, defStyleAttr, 0);

        border = typedArray.getDimensionPixelOffset(R.styleable.OverlayView_border, 20);
        sure = typedArray.getInt(R.styleable.OverlayView_sureWH, SURE_WIDTH);
        sureWeight = typedArray.getFloat(R.styleable.OverlayView_sureWeight, 0.7f);
        ratio = typedArray.getFloat(R.styleable.OverlayView_ratio, 4 / 3f);
        maskColor = typedArray.getColor(R.styleable.OverlayView_maskColor, Color.argb(150, 0, 0, 0));
        rectColor = typedArray.getColor(R.styleable.OverlayView_rectColor, Color.WHITE);
        scaleEnabled = typedArray.getBoolean(R.styleable.OverlayView_scaleEnabled, false);
        translateEnabled = typedArray.getBoolean(R.styleable.OverlayView_translateEnabled, false);

      /*  Log.d(TAG, "parseAttribute:border=" + border);
        Log.d(TAG, "parseAttribute:sure=" + sure);
        Log.d(TAG, "parseAttribute:sureWeight=" + sureWeight);
        Log.d(TAG, "parseAttribute:ratio=" + ratio);
        Log.d(TAG, "parseAttribute:maskColor=" + maskColor);
        Log.d(TAG, "parseAttribute:rectColor=" + rectColor);
        Log.d(TAG, "parseAttribute:scaleEnabled=" + scaleEnabled);
        Log.d(TAG, "parseAttribute:translateEnabled=" + translateEnabled);*/
        typedArray.recycle();

    }


    private void init(Context context) {
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(rectColor);
        paint.setStrokeWidth(ResourceUtils.dpTopx(1));

        eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        //手势监听
        gestureDetector = new GestureDetector(context, onGestureListener);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画遮罩
        canvas.drawColor(maskColor);
        //画矩形
        if(drawFrameRect){
            canvas.drawRect(frameRect, paint);
        }
        //擦掉中间
        canvas.drawRect(frameRect, eraser);
        //画4个角
        if(drawCornerLine){
            drawCornerLine(canvas);
        }
        //画图
        drawImage(canvas);
    }

    /**
     * 画4个角
     *
     * @param canvas
     */
    private void drawCornerLine(Canvas canvas) {
        paint.setStrokeWidth(cornerLineWidth);
        // 左上
        canvas.drawLine(frameRect.left, frameRect.top, frameRect.left + cornerLength, frameRect.top, paint);
        canvas.drawLine(frameRect.left, frameRect.top, frameRect.left, frameRect.top + cornerLength, paint);
        //左下
        canvas.drawLine(frameRect.left, frameRect.bottom, frameRect.left + cornerLength, frameRect.bottom, paint);
        canvas.drawLine(frameRect.left, frameRect.bottom, frameRect.left, frameRect.bottom - cornerLength, paint);
        //右上
        canvas.drawLine(frameRect.right, frameRect.top, frameRect.right - cornerLength, frameRect.top, paint);
        canvas.drawLine(frameRect.right, frameRect.top, frameRect.right, frameRect.top + cornerLength, paint);
        //右下
        canvas.drawLine(frameRect.right, frameRect.bottom, frameRect.right - cornerLength, frameRect.bottom, paint);
        canvas.drawLine(frameRect.right, frameRect.bottom, frameRect.right, frameRect.bottom - cornerLength, paint);


    }

    /**
     * 画图片
     * @param canvas
     */
    protected void drawImage(Canvas canvas){

    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //计算出的宽高
        int width = 0;
        int height = 0;

        //父组件提供的最大宽高
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        //最小尺寸
        int minWidth = getFrameRectMinWidth() + border * 2;
        int minHeight = getFrameRectMinHeight() + border * 2;

        width=measure(MeasureSpec.getMode(widthMeasureSpec),widthSize,minWidth);
        height=measure(MeasureSpec.getMode(heightMeasureSpec),heightSize,minHeight);
        setMeasuredDimension(width, height);

    }

    private int measure(int mode, int max, int min) {
        switch (mode) {
            case MeasureSpec.EXACTLY:
                //确切的 match_parent和具体值
                return max;
            case MeasureSpec.AT_MOST:
                //父组件提供了最大值  wrap_content
                //根据字体大小计算宽度
                return min;
            case MeasureSpec.UNSPECIFIED://父组件未提供尺寸约束,可以是任何尺寸,一般不会出现这个情况
                return Math.max(max, min);
        }
        return max;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        resetFrameRect(w, h);
    }


    /**
     * 重置中间矩形的大小
     *
     * @param w
     * @param h
     */
    private void resetFrameRect(int w, int h) {
        float width = 0;
        float height = 0;
        //宽度确定
        if (sure == SURE_WIDTH) {
            width = w * sureWeight;
            width = validateWidth(width, w);
            height = width / ratio;
            height = validateHeight(height, h);
        } else {
            height = h * sureWeight;
            height = validateHeight(height, h);
            width = height * ratio;
            width = validateWidth(width, w);
        }
        frameRect.left = (w - width) / 2;
        frameRect.right = w - frameRect.left;
        frameRect.top = (h - height) / 2;
        frameRect.bottom = h - frameRect.top;
//        Log.d(TAG, "resetFrameRect:frameRect=" + frameRect);

    }

    /**
     * 验证宽度
     *
     * @param width
     * @param viewWidth
     * @return
     */
    private float validateWidth(float width, int viewWidth) {
        int maxWidth = getFrameRectMaxWidth(viewWidth);
        int minWidth = getFrameRectMinWidth();
        if (width > maxWidth) {
            return maxWidth;
        } else if (width < minWidth) {
            return minWidth;
        }
        return width;
    }

    /**
     * 验证高度
     *
     * @param height
     * @param viewHeight
     * @return
     */
    private float validateHeight(float height, int viewHeight) {
        int maxHeight = getFrameRectMaxHeight(viewHeight);
        int minHeight = getFrameRectMinHeight();
        if (height > maxHeight) {
            return maxHeight;
        } else if (height < minHeight) {
            return minHeight;
        }
        return height;
    }

    //最小宽度
    private int getFrameRectMinWidth() {
        return cornerLength * 2 + 30;
    }

    //最大宽度
    private int getFrameRectMaxWidth(int w) {
        return w - 2 * border;
    }


    //最小高度
    private int getFrameRectMinHeight() {
        return cornerLength * 2 + 30;
    }

    //最大高度
    private int getFrameRectMaxHeight(int h) {
        return h - 2 * border;
    }


    /**
     * 触摸事件监听
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (translateEnabled || scaleEnabled) {
            super.onTouchEvent(event);
            if (scaleEnabled) {
                boolean b = downCorner(event);
                if (!b && translateEnabled) {
                    //只有手指在矩形内才能移动
                    if (frameRect.contains(event.getX(), event.getY())) {
                        gestureDetector.onTouchEvent(event);
                        return true;
                    }
                }
                return b;

            } else {
                //只能移动
                gestureDetector.onTouchEvent(event);
                return true;
            }
        }

        return super.onTouchEvent(event);
    }

    /**
     * 触摸的是四边
     *
     * @param event
     * @return
     */
    private boolean downCorner(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                touchCorner = -1;
                break;
            case MotionEvent.ACTION_DOWN:
                //计算触摸的角
                float x = event.getX();
                float y = event.getY();
                touchRect.set(x - TOUCH_RECT_SIZE, y - TOUCH_RECT_SIZE, x + TOUCH_RECT_SIZE, y + TOUCH_RECT_SIZE);
                if (touchRect.contains(frameRect.left, frameRect.top)) {
                    touchCorner = CORNER_LEFT_TOP;
                    return true;
                } else if (touchRect.contains(frameRect.left, frameRect.bottom)) {
                    touchCorner = CORNER_LEFT_BOTTOM;
                    return true;
                } else if (touchRect.contains(frameRect.right, frameRect.top)) {
                    touchCorner = CORNER_RIGHT_TOP;
                    return true;
                } else if (touchRect.contains(frameRect.right, frameRect.bottom)) {
                    touchCorner = CORNER_RIGHT_BOTTOM;
                    return true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                return handleScale(event);
        }
        return false;
    }


    /**
     * 拉动角落放大缩小到触摸位置
     *
     * @param event
     * @return
     */
    private boolean handleScale(MotionEvent event) {
//        Log.d(TAG, "scaleFrameRect:touchCorner=" + touchCorner);
        float x = event.getX();
        float y = event.getY();
        if (touchCorner == CORNER_LEFT_TOP) {
            scaleTo(x, y, frameRect.right, frameRect.bottom);
            return true;
        } else if (touchCorner == CORNER_LEFT_BOTTOM) {
            scaleTo(x, frameRect.top, frameRect.right, y);
            return true;
        } else if (touchCorner == CORNER_RIGHT_TOP) {
            scaleTo(frameRect.left, y, x, frameRect.bottom);
            return true;
        } else if (touchCorner == CORNER_RIGHT_BOTTOM) {
            scaleTo(frameRect.left, frameRect.top, x, y);
            return true;
        }
        return false;
    }

    /**
     * 计算frameRect 坐标的合法性并移动
     *
     * @param left
     * @param top
     * @param right
     * @param bottom
     */
    private void scaleTo(float left, float top, float right, float bottom) {
        int minWidth = getFrameRectMinWidth();
        int minHeight = getFrameRectMinHeight();
        if (right - left < minWidth) {
            left = frameRect.left;
            right = frameRect.right;
        }
        if (bottom - top < minHeight) {
            bottom = frameRect.bottom;
            top = frameRect.top;
        }
        left = Math.max(left, border);
        top = Math.max(top, border);
        right = Math.min(right, getWidth() - border);
        bottom = Math.min(bottom, getHeight() - border);

        frameRect.set(left, top, right, bottom);
        invalidate();
    }

    /**
     * 移动
     *
     * @param disX >0左移
     * @param disY >0 上移
     */
    private void translate(float disX, float disY) {
//        Log.d(TAG, "translate:disX=" + disX + ",disY=" + disY);
        //右移
        if (disX < 0) {
            if (frameRect.right - disX > getWidth() - border) {
                disX = frameRect.right - getWidth() + border;
            }
        } else {
            //左移
            if (frameRect.left - disX < border) {
                disX = frameRect.left - border;
            }
        }
        //上移
        if (disY > 0) {
            if (frameRect.top - disY < border) {
                disY = frameRect.top - border;
            }
        } else {
            //下移
            if (frameRect.bottom - disY > getHeight() - border) {
                disY = frameRect.bottom - getHeight() + border;
            }
        }
        frameRect.offset(-disX, -disY);
        invalidate();
    }

    /**
     * 获取中间的矩形
     * @return
     */
    public Rect getRect(){
        Rect rect=new Rect();
        rect.left= (int) frameRect.left;
        rect.top= (int) frameRect.top;
        rect.right= (int) frameRect.right;
        rect.bottom= (int) frameRect.bottom;
        return rect;
    }

    public RectF getRectRatio(){
        RectF rectF=new RectF();
        //开始左坐标的百分比
        float leftRatio = frameRect.left / getWidth();
        float topRatio = frameRect.top / getHeight();
        float rightRatio = frameRect.right / getWidth();
        float bottomRatio = frameRect.bottom / getHeight();
        rectF.left=leftRatio;
        rectF.top=topRatio;
        rectF.right=rightRatio;
        rectF.bottom=bottomRatio;
        return rectF;

    }

    public void setRatio(float ratio) {
        this.ratio = ratio;
    }

    public void setSure(int sure) {
        this.sure = sure;
    }

    public void setSureWeight(float sureWeight) {
        this.sureWeight = sureWeight;
    }

    public void setScaleEnabled(boolean scaleEnabled) {
        this.scaleEnabled = scaleEnabled;
    }

    public void setTranslateEnabled(boolean translateEnabled) {
        this.translateEnabled = translateEnabled;
    }

}
